package com.chinaunicom.emergency.security;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;


/**
 * @author  liliang
 * @date 
 *  一键加密解密     安卓版   
 */
public final class RSAUtils
{
	private static String RSA = "RSA";
	
	private static PublicKey publicKey ;
	private static String publicKeyStr="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr8xXchQd5RPiFHPQwAo3\n" +
			"5xBgw3+hd4mtdOwI/oMGPLSsDQeeLAIFPvsaMOJw1Q2+A7cxeqQ8KnEG7jPmAjcp\n" +
			"t0TjNrDLI8h16+sLoaf4OsXFFIZd6kd86w6ENXbDggR8NBlvFqXJa/aau7vnqJ2H\n" +
			"v/FkOONlQjeY6QJnT4CjXAp83A8ntww/sjQCVpm5TNRnOFEBF+EjNW3zuH2YR9FB\n" +
			"dXCX1oauPlTes2E1pDNWsL2aB6Hyw9/aofXfPfQMTXBHS1mfGr1HSa8V9sMkjpXN\n" +
			"2fJbYYPJPk9zplIGFLgp9TpZoAWOs02iBvxQTGpA0ODuO5kio8/pu5L9upd8Aal8\n" +
			"lwIDAQAB";

	/**
	 * 随机生成RSA密钥对(默认密钥长度为1024)
	 * 
	 * @return
	 */
	private static KeyPair generateRSAKeyPair()
	{
		return generateRSAKeyPair(1024);
	}
 
	/**
	 * 随机生成RSA密钥对
	 * 
	 * @param keyLength
	 *            密钥长度，范围：512～2048<br>
	 *            一般1024
	 * @return
	 */
	private static KeyPair generateRSAKeyPair(int keyLength)
	{
		try
		{
			KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA,new org.bouncycastle.jce.provider.BouncyCastleProvider());
			kpg.initialize(keyLength);
			return kpg.genKeyPair();
		} catch (Throwable e)
		{
			e.printStackTrace();
			return null;
		}
	}
 
	/**
	 * 用公钥加密 <br>
	 * 每次加密的字节数，不能超过密钥的长度值减去11
	 * 
	 
	 * @return 加密后的 数据
	 */
	public static String encryptData(String data )
	{
		try
		{
			if (publicKey==null) {
				publicKey=loadPublicKey(publicKeyStr);
			}
//			Cipher cipher = Cipher.getInstance(RSA);
			Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			// 编码前设定编码方式及密钥
			cipher.init(Cipher.ENCRYPT_MODE, publicKey);
			// 传入编码数据并返回编码结果
            BASE64Encoder encoder = new BASE64Encoder();

			return encoder.encode(cipher.doFinal(data.getBytes()));
			
			 
		} catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}
 

	/**
	 * 通过公钥byte[](publicKey.getEncoded())将公钥还原，适用于RSA算法
	 * 
	 * @param keyBytes
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 */
	private static PublicKey getPublicKey(byte[] keyBytes) throws NoSuchAlgorithmException,
			InvalidKeySpecException
	{
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(RSA);
		PublicKey publicKey = keyFactory.generatePublic(keySpec);
		return publicKey;
	}
 
	/**
	 * 通过私钥byte[]将公钥还原，适用于RSA算法
	 * 
	 * @param keyBytes
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 */
	private static PrivateKey getPrivateKey(byte[] keyBytes) throws NoSuchAlgorithmException,
			InvalidKeySpecException
	{
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(RSA);
		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
		return privateKey;
	}
 
	/**
	 * 使用N、e值还原公钥
	 * 
	 * @param modulus
	 * @param publicExponent
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 */
	private static PublicKey getPublicKey(String modulus, String publicExponent)
			throws NoSuchAlgorithmException, InvalidKeySpecException
	{
		BigInteger bigIntModulus = new BigInteger(modulus);
		BigInteger bigIntPrivateExponent = new BigInteger(publicExponent);
		RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent);
		KeyFactory keyFactory = KeyFactory.getInstance(RSA);
		PublicKey publicKey = keyFactory.generatePublic(keySpec);
		return publicKey;
	}
 
	/**
	 * 使用N、d值还原私钥
	 * 
	 * @param modulus
	 * @param privateExponent
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 */
	private static PrivateKey getPrivateKey(String modulus, String privateExponent)
			throws NoSuchAlgorithmException, InvalidKeySpecException
	{
		BigInteger bigIntModulus = new BigInteger(modulus);
		BigInteger bigIntPrivateExponent = new BigInteger(privateExponent);
		RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent);
		KeyFactory keyFactory = KeyFactory.getInstance(RSA);
		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
		return privateKey;
	}
 
	/**
	 * 从字符串中加载公钥
	 * 
	 * @param publicKeyStr
	 *            公钥数据字符串
	 * @throws Exception
	 *             加载公钥时产生的异常
	 */
	private static PublicKey loadPublicKey(String publicKeyStr) throws Exception
	{
		try
		{
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] buffer = decoder.decodeBuffer(publicKeyStr);
			KeyFactory keyFactory = KeyFactory.getInstance(RSA);
			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
			return (RSAPublicKey) keyFactory.generatePublic(keySpec);
		} catch (NoSuchAlgorithmException e)
		{
			throw new Exception("无此算法");
		} catch (InvalidKeySpecException e)
		{
			throw new Exception("公钥非法");
		} catch (NullPointerException e)
		{
			throw new Exception("公钥数据为空");
		}
	}

 
	/**
	 * 从文件中输入流中加载公钥
	 * 
	 * @param in
	 *            公钥输入流
	 * @throws Exception
	 *             加载公钥时产生的异常
	 */
	private static PublicKey loadPublicKey(InputStream in) throws Exception
	{
		try
		{
			return loadPublicKey(readKey(in));
		} catch (IOException e)
		{
			throw new Exception("公钥数据流读取错误");
		} catch (NullPointerException e)
		{
			throw new Exception("公钥输入流为空");
		}
	}

 
	/**
	 * 读取密钥信息
	 * 
	 * @param in
	 * @return
	 * @throws IOException
	 */
	private static String readKey(InputStream in) throws IOException
	{
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		String readLine = null;
		StringBuilder sb = new StringBuilder();
		while ((readLine = br.readLine()) != null)
		{
			if (readLine.charAt(0) == '-')
			{
				continue;
			} else
			{
				sb.append(readLine);
				sb.append('\r');
			}
		}
 
		br.close();
		return sb.toString();
	}
 
	/**
	 * 打印公钥信息
	 * 
	 * @param publicKey
	 */
	private static void printPublicKeyInfo(PublicKey publicKey)
	{
		RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
		System.out.println("----------RSAPublicKey----------");
		System.out.println("Modulus.length=" + rsaPublicKey.getModulus().bitLength());

		System.out.println("Modulus=" + rsaPublicKey.getModulus().toString());
		System.out.println("PublicExponent.length=" + rsaPublicKey.getPublicExponent().bitLength());
		System.out.println("PublicExponent=" + rsaPublicKey.getPublicExponent().hashCode());
	}
 
	private static void printPrivateKeyInfo(PrivateKey privateKey)
	{
		RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
		System.out.println("----------RSAPrivateKey ----------");
		System.out.println("Modulus.length=" + rsaPrivateKey.getModulus().bitLength());
		System.out.println("Modulus=" + rsaPrivateKey.getModulus().toString());
		System.out.println("PrivateExponent.length=" + rsaPrivateKey.getPrivateExponent().bitLength());
		System.out.println("PrivatecExponent=" + rsaPrivateKey.getPrivateExponent().toString());
 
	}

	public static void main(String[] args) throws Exception {
//        System.out.println(Base64Utils.byteArrayToBase64(generateRSAKeyPair().getPublic().getEncoded()));
//        System.out.println(Base64Utils.byteArrayToBase64(generateRSAKeyPair().getPrivate().getEncoded()));
//        String dstr = encryptData("234134");
//        System.out.println(dstr);
		printPublicKeyInfo(loadPublicKey(publicKeyStr));
		BASE64Decoder decoder = new BASE64Decoder();
		byte[] bytes = decoder.decodeBuffer("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr8xXchQd5RPiFHPQwAo35xBgw3+hd4mtdOwI/oMGPLSsDQeeLAIFPvsaMOJw1Q2+A7cxeqQ8KnEG7jPmAjcpt0TjNrDLI8h16+sLoaf4OsXFFIZd6kd86w6ENXbDggR8NBlvFqXJa/aau7vnqJ2Hv/FkOONlQjeY6QJnT4CjXAp83A8ntww/sjQCVpm5TNRnOFEBF+EjNW3zuH2YR9FBdXCX1oauPlTes2E1pDNWsL2aB6Hyw9/aofXfPfQMTXBHS1mfGr1HSa8V9sMkjpXN2fJbYYPJPk9zplIGFLgp9TpZoAWOs02iBvxQTGpA0ODuO5kio8/pu5L9upd8Aal8lwIDAQAB");
		System.out.println(new String(bytes));
    }
}
